#include "authorization.h"
#include "client.h"

QString globalNickname;
SOCKET clientSock;
SOCKET clientSocket;

Authorization::Authorization(QWidget *parent)
    : QWidget{parent}
{
    connectServer();
    buildEntrance();
    connection();

}

void Authorization::connectServer()
{
    clientSock = socket(AF_INET, SOCK_STREAM, 0);
    if(clientSock < 0)
    {
        std::cout << "CLIENT: Socket creation error" << std::endl;
        exit(0);
    }
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = INADDR_ANY;

    if(::connect(clientSock, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0)
    {
        std::cout << "ERROR CLIENT: Failed to connect to the server";
        exit(1);
    }
}

void Authorization::Registration()
{
    authPageLabel->setText(tr("already have an account?"));
    topNameLabel->setText(tr("Registration"));
    authButton->setText(tr("Register"));
    authPageButton->setText(tr("enter"));
    nickEdit->setText("");
    passwordEdit->setText("");
    infoLabel->setText("");
}

void Authorization::Entrance()
{
    authPageLabel->setText(tr("no account?"));
    topNameLabel->setText(tr("Entrance"));
    authButton->setText(tr("Enter"));
    authPageButton->setText(tr("register"));
    nickEdit->setText("");
    passwordEdit->setText("");
    infoLabel->setText("");
}

void Authorization::buildEntrance()
{
    vLayout = new QVBoxLayout(this);
    hLayout = new QHBoxLayout(this);
    formLayout = new QFormLayout(this);
    topNameLabel = new QLabel(tr("Entrance"), this);
    topNameLabel->setAlignment(Qt::AlignCenter);
    topNameLabel->setFont(QFont(tr("Terminus"), 20));
    authPageLabel = new QLabel(tr("no account?"), this);
    authPageLabel->setAlignment(Qt::AlignCenter);
    nickEdit = new QLineEdit(this);
    passwordEdit = new QLineEdit(this);
    authPageButton = new QPushButton(tr("register"));
    authButton = new QPushButton(tr("Enter"));
    infoLabel = new QLabel(this);

    formLayout->addRow(tr("Nickname: "), nickEdit);
    formLayout->addRow(tr("Password: "), passwordEdit);

    hLayout->addWidget(authPageLabel, 0);
    hLayout->addWidget(authPageButton, 0, Qt::AlignLeft);

    vLayout->addWidget(topNameLabel, 5, Qt::AlignVCenter);
    vLayout->addLayout(formLayout, 0);
    vLayout->addLayout(hLayout, 2);
    vLayout->addWidget(infoLabel);
    vLayout->addWidget(authButton);
}

void Authorization::connection()
{
    connect(authPageButton, &QPushButton::clicked, this, &Authorization::regimeChange);
    connect(authButton, &QPushButton::clicked, this, &Authorization::authActions);
}

//slots

void Authorization::regimeChange()
{
    QPushButton* button = static_cast<QPushButton*>(sender());
    if(button->text() == "register")
    {
        Registration();
    }
    else if(button->text() == "enter")
    {
        Entrance();
    }
}

void Authorization::authActions()
{
    QPushButton* button = static_cast<QPushButton*>(sender());
    QString sqlQuery;
    std::string sqlQueryStd;
    char buffer[BUFFER_SIZE];

    if(button->text() == "Register")
    {
        QString nicknameReg = nickEdit->text();
        int count = 0;
        bool checkNick = false;
        int countUnderlining = 0;

        if(nicknameReg.size() > 15 || nicknameReg == "" || nicknameReg.size() < 5)
        {
            checkNick = true;
        }
        for(QChar ch : nicknameReg)
        {
            if(!ch.isLetterOrNumber())
            {
                checkNick = true;
                if(ch == '_' && countUnderlining < 2)
                {
                    checkNick = false;
                    ++countUnderlining;
                }
            }
        }
        if(checkNick)
        {
            infoLabel->setText("Only numbers and letters are allowed in the name(no more than 2 underscores),\n "
                        "the nickname must not be less than 5\n and no more than 15 characters");
        }
        else
        {
            ++count;
        }

        QString password = passwordEdit->text();
        bool checkPassword = false;

        if(password.size() > 15 || password == "" || password.size() < 8)
        {
            checkPassword = true;
        }
        for(QChar ch : password)
        {
            if(ch.isSpace())
            {
                checkPassword = true;
            }
        }
        if(checkPassword)
        {
            infoLabel->setText("Spaces are not allowed in the password,\n "
                     "the password must not be less than 8\n and no more than 15 characters.");
        }
        else
        {
            ++count;
        }

        sqlQuery = QString("SELECT COUNT(*) FROM Authorization WHERE nickName = '%1'").arg(nicknameReg);
        sqlQueryStd = sqlQuery.toStdString();

        send(clientSock, sqlQueryStd.c_str(), sqlQueryStd.length(), 0);
        memset(buffer, 0, sizeof(buffer));
        recv(clientSock, buffer, sizeof(buffer), 0);

        if(!(atoi(buffer) > 0))
        {

            ++count;
        }
        else
        {
            infoLabel->setText("this nickname is already in use");
        }

        if(count == 3)
        {
            infoLabel->setText("successful registration");
            globalNickname = nickEdit->text();
            password = passwordEdit->text();
            sqlQuery = QString("INSERT INTO Authorization(nickName, Password) VALUES('%1', '%2')").arg(globalNickname).arg(password);
            sqlQueryStd = sqlQuery.toStdString();
            send(clientSock, sqlQueryStd.c_str(), sqlQueryStd.length(), 0);
            Client* client = new Client;
            client->show();
            close();
        }

    }
    else if(button->text() == "Enter")
    {
        bool checking;
        sqlQuery = QString("SELECT COUNT(*) FROM Authorization WHERE nickName = '%1' AND Password = '%2'").arg(nickEdit->text()).arg(passwordEdit->text());
        sqlQueryStd = sqlQuery.toStdString();
        send(clientSock, sqlQueryStd.c_str(), sqlQueryStd.length(), 0);
        memset(buffer, 0, sizeof(buffer));
        recv(clientSock, buffer, sizeof(buffer), 0);
        if(atoi(buffer) > 0)
        {
            checking = true;
        }
        else
        {
            checking = false;
        }

        if(checking)
        {
            globalNickname = nickEdit->text();
            QString nickNameServer = QString("add_user:'%1'").arg(clientStartNickname());
            std::string nickNameServerStr = nickNameServer.toStdString();
            send(clientSock, nickNameServerStr.c_str(), nickNameServerStr.length(), 0);
            Client* client = new Client;
            client->show();
            this->close();

        }
        else if(!checking)
        {
            passwordEdit->setText("");
            infoLabel->setText("Invalid nickname or password");
        }
    }
}

QString clientStartNickname()
{
    return globalNickname;
}
